package utils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import main.Pair;
import main.Solution;

public class IOUtils {

	
	public static final String NO_SOL_MSG = "NOSOL";
	public static final String lineSeperator = System.getProperty("line.separator");
	
	public static File generateInstanceFile(int numOfVertices, String filePath) {
		String line = "extermal " + numOfVertices + " 0";
		File f = new File(filePath);
		FileWriter fw =null;
		try {
			
			fw = new FileWriter(f);
			fw.write(line);
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		return f;
	}

	
	public static void generateMapFile(String filePath, Map<Integer,Pair<Integer, Integer>> litToEdge, int[] sumLits){
		File f = new File(filePath);
		FileWriter fw =null;
		try {
			
			fw = new FileWriter(f);

			for (Map.Entry<Integer,Pair<Integer, Integer>> mapEntry : litToEdge.entrySet()){
				int lit = mapEntry.getKey().intValue();
				int from = mapEntry.getValue().first.intValue();
				int to = mapEntry.getValue().second.intValue();
				String line = "edge " + Integer.toString(from) + " " + Integer.toString(to) + " " + Integer.toString(lit) + lineSeperator;
				fw.write(line);
			}
			StringBuilder lineSB = new StringBuilder();
			lineSB.append("sum binary ");
			for (int lit:sumLits){ 
				lineSB.append(lit).append(" ");
			}
			lineSB.append(" 0").append(lineSeperator);
			fw.write(lineSB.toString());
			
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void writeCnfToFile(Vector<int[]> cnf, int literalCount, String cnfFileName) {
		FileWriter fw =null;
		try {
			File f = new File(cnfFileName);
			fw = new FileWriter(f);
			fw.write("p cnf " + literalCount + " " + cnf.size() +"\n");
			cnfToFileWriter(cnf, fw);
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	public static void cnfToFileWriter(Vector<int[]> cnf, FileWriter fw) throws IOException {
		
			Iterator<int[]> it = cnf.iterator();
			while (it.hasNext()){
				int[] clause = it.next();
				String clauseString = "";
				for (int i = 0 ; i < clause.length; i++){
					clauseString += clause[i] + " "; 
				}
				fw.write(clauseString + "0");
//				if (it.hasNext()){
					fw.write(lineSeperator);
//				}
			}
			
			fw.flush();
			
		
	}
	
	
	public static void writeSolution(int[][]coloring, String solFileName){
		if (coloring != null)
			MatrixUtils.saveColoringToFile(coloring, solFileName);
		
		else{
			FileWriter fw =null;
			try {
				File f = new File(solFileName);
				fw = new FileWriter(f);
				fw.write(NO_SOL_MSG);
				fw.flush();
				
			} catch (IOException e) {
				e.printStackTrace();
			}finally{
				if (fw != null){
					try {
						fw.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}


	public static void generateScriptFile(String fileName, Vector<int[]> cnf, int[] sumBits) {
		try {
			
			String lineSeperator = IOUtils.lineSeperator;
			File res = new File(fileName);
			
			FileWriter fw =null;
			try {
				fw = new FileWriter(res);
				fw.write("cnf" + lineSeperator);
				IOUtils.cnfToFileWriter(cnf, fw);
				
				fw.write("end" + lineSeperator);
				String mode = "binary";
				
				fw.write("minimize " + mode +" ");
				for (int i = 0; i < sumBits.length; i++) {
					fw.write(sumBits[i] + " ");
				}
								
				fw.write("0" + lineSeperator);
				fw.write("kill" + lineSeperator);
				fw.flush();
				
			} catch (IOException e) {
				e.printStackTrace();
			}finally{
				if (fw != null){
					try {
						fw.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void generateSolFile(String solFilePath, Solution sol) {
		FileWriter fw =null;
		try {
			File f = new File(solFilePath);
			fw = new FileWriter(f);
			fw.write("extremal "+ sol.getNumOfVertices() + " " + sol.getNumOfEdges() + lineSeperator);
			for (int i = 0; i < sol.getEdges().length; i++) {
				for (int j = i+1; j < sol.getEdges().length; j++){
					if (sol.getEdges()[i][j] ==1){
						fw.write("edge " + Integer.toString(i+1) + " " + Integer.toString(j+1) + lineSeperator);
					}
				}
			}
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	public static void generateDotFile(String dotFilePath, int[][] sol) {
		FileWriter fw =null;
		try {
			File f = new File(dotFilePath);
			fw = new FileWriter(f);
			fw.write("digraph G{"+lineSeperator);
			fw.write("edge ["+lineSeperator);
			fw.write("arrowhead=\"none\""+lineSeperator);
			fw.write("];"+lineSeperator);
			for (int i = 0; i < sol.length; i++) {
				for (int j = i+1; j < sol.length; j++){
					if (sol[i][j] ==1){
						fw.write(i+" -> "+j+";"+lineSeperator);
					}
				}
			}
			
			fw.write("}"+lineSeperator);
			fw.flush();
			
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if (fw != null){
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
